﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using System.Web;
namespace Ymatou.ServiceCenter
{
    public static class UriExtensions
    {
        public static IDictionary<string, string> GetParameters(this Uri uri)
        {
            if (uri == null)
                return null;
            IDictionary<string, string> dic = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
            string[] array1 = uri.Query.TrimStart('?').Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
            if (array1.Length <= 0)
                return null;
            foreach (string item in array1)
            {
                if (!item.Contains('='))
                    continue;
                string[] array2 = item.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                dic.Add(Uri.UnescapeDataString(array2[0]), Uri.UnescapeDataString(array2[1]));
            }
            return dic;
        }

        public static Uri ToNewUri(this Uri uri, IDictionary<string, string> parameters)
        {
            if (parameters == null)
                return uri;
            bool first = true;
            var sb = new StringBuilder();
            sb.Append(uri.Scheme).Append("://");
            sb.Append(uri.Host);
            sb.Append(uri.LocalPath);
            foreach (var item in parameters)
            {
                if (first)
                {
                    sb.Append(!sb.ToString().Contains("?") ? '?' : '&');
                    first = false;
                }
                else
                    sb.Append('&');
                sb.Append(Uri.EscapeDataString(item.Key) + "=" + Uri.EscapeDataString(item.Value));
            }
            return new Uri(sb.ToString());
        }

        public static string GetRequestId(this HttpContext httpContext)
        {
            if (httpContext == null)
                return null;
            string requestId = HttpContext.Current == null ? null : HttpContext.Current.Request.Headers.Get("RequestId");
            return requestId;
        }

        public static string GetRequestId(this HttpRequest httpRequest)
        {
            if (httpRequest == null)
                return null;
            string requestId = httpRequest.Headers.Get("RequestId");
            return requestId;
        }


        public static string GetClientIp(this HttpRequest httpRequest)
        {
            return Utils.GetWebClientIp(httpRequest);
        }

        public static string GetServerIpLink(this HttpRequest httpRequest)
        {
            return Utils.GetServerIpLink(httpRequest);
        }

        public static string GetLocalServerIp(this HttpRequest httpRequest)
        {
            return Utils.LocalIp;
        }

        public static string GetRequestId(this HttpRequestMessage httpRequestMessage)
        {
            try
            {
                if (httpRequestMessage == null)
                    return null;
                return httpRequestMessage.Headers.Contains("RequestId")
                    ? httpRequestMessage.Headers.GetValues("RequestId").FirstOrDefault()
                    : null;
            }
            catch
            {
                return null;
                // ignored
            }
        }

        private static string GetClientIpAddress(HttpRequestMessage request)
        {
            try
            {
                if (request == null)
                    return string.Empty;
                string clientIp = request.Headers.Contains("ClientIp")
    ? request.Headers.GetValues("ClientIp").FirstOrDefault()
    : null;
                if (!string.IsNullOrWhiteSpace(clientIp))
                    return clientIp;
                clientIp = Utils.GetWebClientIp(HttpContext.Current == null ? null : HttpContext.Current.Request);
                if (!string.IsNullOrWhiteSpace(clientIp))
                    return clientIp;
                const string httpContext = "MS_HttpContext";
                const string remoteEndpointMessage ="System.ServiceModel.Channels.RemoteEndpointMessageProperty";
                const string owinContext = "MS_OwinContext";
                // Web-hosting. Needs reference to System.Web.dll
                if (request.Properties.ContainsKey(httpContext))
                {
                    dynamic ctx = request.Properties[httpContext];
                    if (ctx != null)
                    {
                        return ctx.Request.UserHostAddress;
                    }
                }
                // Self-hosting. Needs reference to System.ServiceModel.dll. 
                if (request.Properties.ContainsKey(remoteEndpointMessage))
                {
                    dynamic remoteEndpoint = request.Properties[remoteEndpointMessage];
                    if (remoteEndpoint != null)
                    {
                        return remoteEndpoint.Address;
                    }
                }
                // Self-hosting using Owin. Needs reference to Microsoft.Owin.dll. 
                if (request.Properties.ContainsKey(owinContext))
                {
                    dynamic context = request.Properties[owinContext];
                    if (context != null)
                    {
                        return context.Request.RemoteIpAddress;
                    }
                }
            }
            catch
            {
                // ignored
            }
            return null;
        }

        public static string GetClientIp(this HttpRequestMessage request)
        {
            try
            {
                if (request == null)
                    return null;
                string result = GetClientIpAddress(request);
                if (string.IsNullOrWhiteSpace(result))
                    return result;
                if (result.Contains(":"))
                {
                    result = result.Replace("::ffff:", "");
                }
                if (result.Contains(","))
                {
                    result = result.Split(',')[0];
                }
                return result;
            }
            catch
            {
                return null;
            }

        }

        public static string GetServerIpLink(this HttpRequestMessage request)
        {
            try
            {
                if (request == null)
                    return null;
                string serverIpLink = request.Headers.Contains("ServerIpLink") ? request.Headers.GetValues("ServerIpLink").FirstOrDefault() : null;
                serverIpLink = string.IsNullOrWhiteSpace(serverIpLink) ? Utils.LocalIp : string.Concat(serverIpLink, ",", Utils.LocalIp);
                return serverIpLink;
            }
            catch
            {
                return null;
            }

        }

        public static string GetLocalServerIp(this HttpRequestMessage request)
        {
            return Utils.LocalIp;
        }
    }
}
